package com.rxt.thermopro.ui.fragment

import android.graphics.Color
import android.graphics.DashPathEffect
import android.net.Uri
import android.os.Bundle
import androidx.core.app.ShareCompat
import androidx.core.content.ContextCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.app.common.base.BaseFragment
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.Legend
import com.github.mikephil.charting.components.LimitLine
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.IFillFormatter
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.github.mikephil.charting.utils.Utils
import com.rxt.thermopro.R
import com.rxt.thermopro.app.LocalDataDao
import com.rxt.thermopro.bean.ProbeHistoryBean
import com.rxt.thermopro.bean.ProfileBean
import com.rxt.thermopro.ui.chart.HistoryMarkerView
import com.rxt.thermopro.viewmodel.BleMessageViewModel
import com.rxt.thermopro.viewmodel.HistoryChartsViewModel
import kotlinx.android.synthetic.main.fragment_history_charts.*
import kotlinx.android.synthetic.main.fragment_history_charts.chartView
import kotlinx.android.synthetic.main.fragment_temp_graph_page.*
import java.text.SimpleDateFormat
import java.util.*
import android.content.ContentResolver
import android.provider.Settings
import com.rxt.thermopro.ex.is24HourStyle


class HistoryChartsFragment : BaseFragment<HistoryChartsViewModel>() {

    override fun layoutId(): Int {
        return R.layout.fragment_history_charts
    }

    companion object {
        private const val ARG_POSITION = "currentPosition"
        private const val ARG_ADDRESS = "address"
        private const val ARG_INDEX = "probeIndex"
        private const val ARG_DEVICE_TYPE = "deviceType"

        fun newInstance(
            position: Int,
            probeIndex: Int,
            address: String,
            deviceType: Int
        ): HistoryChartsFragment {
            return HistoryChartsFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_POSITION, position)
                    putInt(ARG_INDEX, probeIndex)
                    putInt(ARG_DEVICE_TYPE, deviceType)
                    putString(ARG_ADDRESS, address)
                }
            }
        }
    }

    private var currentPosition = -1
    private var mAddress = ""
    private var probeIndex = -1
    private var mDeviceType = -1
    private var highLimitLine = -1f
    private var lowLimitLine = -1f
    val dateFormat = SimpleDateFormat("dd-MM-yyyy HH:mm")
    private val dateFormat2 = SimpleDateFormat("yyyy-MM-dd-HH-mm")
    private val dateFormat1 = SimpleDateFormat("dd-MM-yyyy hh:mm")

    override fun initView(savedInstanceState: Bundle?) {
        currentPosition = arguments?.getInt(ARG_POSITION, -1) ?: -1
        probeIndex = arguments?.getInt(ARG_INDEX, -1) ?: -1
        mAddress = arguments?.getString(ARG_ADDRESS, "") ?: ""
        mDeviceType = arguments?.getInt(ARG_DEVICE_TYPE, -1) ?: -1

        if (mDeviceType == BleMessageViewModel.DEVICE_TYPE_TP960) {
            probeView.isVisible = false
        }

        mViewModel.historyList.observeInFragment(this, androidx.lifecycle.Observer {
            if (it.probeIndex != -1) {
                viewProbeIndex.text = (it.probeIndex + 1).toString()
//                viewDateTime.text =
//                    dateFormat.format(it.itemList.last().tempTime.toLong()).split(" ")[0]
                viewDateTime.text =
                    LocalDataDao.INSTANCE.formatDateTime(it.itemList.last().tempTime.toLong())
//                tempNUm.text = LocalDataDao.INSTANCE.convertUnit(it.itemList.last().tempNum)
                setProfile(it.profile)

                if (LocalDataDao.INSTANCE.getTempUnit() == LocalDataDao.TEMP_UNIT_F) {
                    val newList = mutableListOf<ProbeHistoryBean>()
                    var minTempNum = 0f
                    var maxTempNum = 0f
                    for (i in 0 until it.itemList.size) {
                        val oldBean = it.itemList[i]
                        val newBean = ProbeHistoryBean(
                            oldBean.probeIndex, oldBean.address,
                            LocalDataDao.INSTANCE.transUnitCToF(oldBean.tempNum),
                            oldBean.tempTime, oldBean.profile, oldBean.historyIndex
                        )
                        newBean.tempNum.toFloatOrNull()?.let { item ->
                            if (item < minTempNum) {
                                minTempNum = item
                            }
                        }
                        newBean.tempNum.toFloatOrNull()?.let { item ->
                            if (item > maxTempNum) {
                                maxTempNum = item
                            }
                        }
                        newList.add(newBean)
                    }
                    if (minTempNum < 0) {
                        minTempNum -= 5
                    }
                    setChart(chartView, newList, minTempNum, maxTempNum)
                } else {
                    var minTempNum = 0f
                    var maxTempNum = 0f
                    for (i in 0 until it.itemList.size) {
                        it.itemList[i].tempNum.toFloatOrNull()?.let { item ->
                            if (item < minTempNum) {
                                minTempNum = item
                            }
                        }
                        it.itemList[i].tempNum.toFloatOrNull()?.let { item ->
                            if (item > maxTempNum) {
                                maxTempNum = item
                            }
                        }
                    }
                    if (minTempNum < 0) {
                        minTempNum -= 5
                    }
                    setChart(chartView, it.itemList, minTempNum, maxTempNum)
                }
            }
        })

        mViewModel.getHistory(mAddress, probeIndex, currentPosition)
        initListener()
    }

    private fun initListener() {
        backButton.setOnClickListener {
            requireActivity().onBackPressed()
        }

        viewShare.setOnClickListener {
            val uri = shareLayout.saveImage()
            uri?.let {
                val type = "image/*"

                startActivity(
                    ShareCompat
                        .IntentBuilder
                        .from(requireActivity())
                        .setType(type)
                        .setStream(Uri.parse(uri)).intent
                )
            }
        }
    }

    private fun setProfile(it: ProfileBean) {
        if (it.highTemperatureNum.isEmpty() && it.lowTemperatureNum.isEmpty() && !it.singleTemp) {
            tempHigh.isInvisible = true
            tempHighImg.isInvisible = true
            tempLow.isInvisible = true
            tempLowImg.isInvisible = true
            profileName.setText(R.string.text_no_profile)
        } else if (it.singleTemp) {
            tempHigh.text = LocalDataDao.INSTANCE.formatHighValueUnit(it)
            tempHigh.isInvisible = false
            tempHighImg.isInvisible = false
            tempLow.isInvisible = true
            tempLowImg.isInvisible = true
            profileName.text = it.name
        } else {
            tempHigh.text = LocalDataDao.INSTANCE.formatHighValueUnit(it)
            tempLow.text = LocalDataDao.INSTANCE.formatLowValueUnit(it)
            tempHigh.isInvisible = false
            tempHighImg.isInvisible = false
            tempLow.isInvisible = false
            tempLowImg.isInvisible = false
            profileName.text = it.name
        }
        imageTag.setImageResource(it.iconRes)

        if (it.highTemperatureNum.isEmpty() && it.lowTemperatureNum.isEmpty() && !it.singleTemp) {
            highLimitLine = -1f
            lowLimitLine = -1f
        } else if (it.singleTemp) {
            highLimitLine = LocalDataDao.INSTANCE.formatHighValueUnitNum(it).toFloat()
        } else {
            highLimitLine = LocalDataDao.INSTANCE.formatHighValueUnitNum(it).toFloat()
            lowLimitLine = LocalDataDao.INSTANCE.formatLowValueUntNum(it).toFloat()
        }
    }


    private fun setChart(
        mChart: LineChart, list: MutableList<ProbeHistoryBean>,
        minTempNum: Float, maxTempNum: Float
    ) {

        var is24 = true
        val currentDateFormat = if (is24HourStyle(requireActivity())) {
            is24 = true
            dateFormat
        } else {
            is24 = false
            dateFormat1
        }

        mChart.apply {
            // background color
            setBackgroundColor(Color.WHITE)
            // disable description text
            description.isEnabled = false
            // enable touch gestures
            setTouchEnabled(true)
            // create marker to display box when values are selected
            val mv = HistoryMarkerView(
                requireContext(), R.layout.custom_marker_view_1,
                list, is24
            )
            // Set the marker to the chart
            mv.chartView = this
            marker = mv
            setDrawGridBackground(false)

            // enable scaling and dragging
            isDragEnabled = true
            setScaleEnabled(false)
            // force pinch zoom along both axis
            setPinchZoom(true)
            legend.isEnabled = false
            setDrawBorders(false)
        }

        var xAxis: XAxis = mChart.xAxis
        // // X-Axis Style // //
        xAxis = mChart.xAxis
        xAxis.setDrawAxisLine(true)
        xAxis.position = XAxis.XAxisPosition.BOTTOM
        xAxis.granularity = 1f;
        // vertical grid lines
        xAxis.setDrawGridLines(false)
//        xAxis.enableGridDashedLine(10f, 10f, 0f)
        xAxis.setLabelCount(5, true)
        if (list.size < 4) {
            xAxis.axisMaximum = 4f
        } else {
            xAxis.axisMaximum = list.size.toFloat()
        }
        xAxis.axisMinimum = 0f
        xAxis.setValueFormatter { value, _ ->
//            println("============>setValueFormatter value=$value")
            var str = ""
            when {
                list.isEmpty() -> {
//                    val date = Date()
//                    date.time = (System.currentTimeMillis() + 60L * 1000 * value).toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date, is24)
//                    str = timeStr.split(" ")[1] + strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM(
                        (System.currentTimeMillis() + 60L * 1000 * value).toLong(),is24)
                }
                list.size < 4 -> {
                    val listSize = list.size
                    val tempTime =
                        if (value.toInt() >= listSize) (list.last().tempTime.toLong() + (value - listSize + 1).toLong() * 60L * 1000L).toString()
                        else list[value.toInt()].tempTime
//                    val date = Date()
//                    date.time = tempTime.toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date, is24)
//                    str = timeStr.split(" ")[1] + strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM( tempTime.toLong(),is24)
                }
                else -> {
                    val listSize = list.size
                    val tempTime =
                        if (value.toInt() >= listSize) (list.last().tempTime.toLong() + (value - listSize + 1).toLong() * 60L * 1000L).toString()
                        else list[value.toInt()].tempTime
//                    val date = Date()
//                    date.time = tempTime.toLong()
//                    val timeStr = currentDateFormat.format(date)
//                    val strTrip = getAMOrPM(date, is24)
//                    str = timeStr.split(" ")[1] + strTrip
                    str=LocalDataDao.INSTANCE.formatTimeAMPM( tempTime.toLong(),is24)
                }
            }
//            println("============>setValueFormatter=$str  timeStr=$timeStr value=$value")
            str
        }

        // // Y-Axis Style // //
        val yAxis: YAxis = mChart.axisLeft

        // disable dual axis (only use LEFT axis)
        mChart.axisRight.isEnabled = false

        // horizontal grid lines
        yAxis.setDrawGridLines(false)
//        yAxis.enableGridDashedLine(10f, 10f, 0f)

        // axis range
        if (maxTempNum != 0f) {
            val newMax = if (maxTempNum < highLimitLine) {
                highLimitLine
            } else {
                maxTempNum
            }
            val a = newMax % 3
            val b = newMax / 3
            val c = b % 5
            val newHighLimit = (b + 5 - c) * 4
            yAxis.axisMaximum = newHighLimit
        } else {
            val newMax = if (LocalDataDao.INSTANCE
                    .convertUnitNum("100").toFloat() < highLimitLine
            ) {
                highLimitLine
            } else {
                LocalDataDao.INSTANCE.convertUnitNum("100").toFloat()
            }
            val a = newMax % 3
            val b = newMax / 3
            val c = b % 5
            val newHighLimit = (b + 5 - c) * 4
            yAxis.axisMaximum = newHighLimit
        }
        yAxis.axisMinimum = minTempNum
        yAxis.setLabelCount(5, true)
        yAxis.setDrawZeroLine(false)

        // draw limit lines behind data instead of on top
        yAxis.setDrawLimitLinesBehindData(true)
        xAxis.setDrawLimitLinesBehindData(true)

        val ll1 = LimitLine(highLimitLine, "${highLimitLine.toInt()}°")
        ll1.lineWidth = 1f
        ll1.enableDashedLine(10f, 10f, 0f)
        ll1.labelPosition = LimitLine.LimitLabelPosition.RIGHT_TOP
        ll1.textColor = resources.getColor(android.R.color.holo_red_light)
        ll1.textSize = 10f
//        ll1.typeface = tfRegular

        val ll2 = LimitLine(lowLimitLine, "${lowLimitLine.toInt()}°")
        ll2.lineWidth = 1f
        ll2.enableDashedLine(10f, 10f, 0f)
        ll2.labelPosition = LimitLine.LimitLabelPosition.RIGHT_BOTTOM
        ll2.textSize = 10f
//        ll2.typeface = tfRegular
        yAxis.removeAllLimitLines()
        // add limit lines
        if (highLimitLine != -1f) {
            yAxis.addLimitLine(ll1)
        }
        if (lowLimitLine != -1f) {
            yAxis.addLimitLine(ll2)
        }

        // add data
        if (list.isNotEmpty()) {
            setData(list, mChart)
        }
        // draw points over time
        mChart.animateX(800)
        // get the legend (only possible after setting data)
        val l = mChart.legend
        // draw legend entries as lines
        l.form = Legend.LegendForm.LINE
    }


    private fun setData(list: MutableList<ProbeHistoryBean>, mChart: LineChart) {
        val values = ArrayList<Entry>()
        for (i in 0 until list.size) {
            val tempNum = if (list[i].tempNum.isNotEmpty()) list[i].tempNum.toFloat() else 0f
            values.add(
                Entry(
                    i.toFloat(),
                    tempNum,
                    resources.getDrawable(R.mipmap.add_device_redpoint)
                )
            )
        }

        val set1: LineDataSet
        if (mChart.data != null &&
            mChart.data.dataSetCount > 0
        ) {
            set1 = mChart.data.getDataSetByIndex(0) as LineDataSet
            set1.values = values
            set1.notifyDataSetChanged()
            mChart.data.notifyDataChanged()
            mChart.notifyDataSetChanged()
        } else {
            // create a dataset and give it a type
            set1 = LineDataSet(values, "DataSet 1")
            set1.setDrawIcons(false)

            // draw dashed line
//            set1.enableDashedLine(10f, 5f, 0f)
            set1.disableDashedLine()
            set1.mode = LineDataSet.Mode.LINEAR_DISCONNECT_ZERO

            // black lines and points
            set1.color = Color.parseColor("#458B74")
            set1.setCircleColor(Color.RED)

            // line thickness and point size
            set1.lineWidth = 1f
            set1.circleRadius = 3f

            // draw points as solid circles
            set1.setDrawCircleHole(true)
            set1.circleHoleColor = Color.WHITE

            // customize legend entry
            set1.formLineWidth = 1f
            set1.formLineDashEffect = DashPathEffect(floatArrayOf(10f, 5f), 0f)
            set1.formSize = 15f

            // text size of values
            set1.valueTextSize = 9f

            // draw selection line as dashed
            set1.enableDashedHighlightLine(10f, 5f, 0f)
            set1.setDrawHighlightIndicators(true)
            set1.setDrawHorizontalHighlightIndicator(false)
            set1.highlightLineWidth = 1F
            set1.highLightColor = resources.getColor(android.R.color.holo_blue_light)
            set1.setDrawValues(false)
            set1.setDrawCircles(false)
            set1.isDrawMaxMinValuesAndCircle = false

            // set the filled area
            set1.setDrawFilled(false)
            set1.fillFormatter =
                IFillFormatter { dataSet, dataProvider -> mChart.axisLeft.axisMinimum }

            // set color of filled area
            if (Utils.getSDKInt() >= 18) {
                // drawables only supported on api level 18 and above
                val drawable = ContextCompat.getDrawable(requireContext(), R.drawable.fade_blue)
                set1.fillDrawable = drawable
            } else {
                set1.fillColor = Color.BLACK
            }
            val dataSets = ArrayList<ILineDataSet>()
            dataSets.add(set1) // add the data sets

            // create a data object with the data sets
            val data = LineData(dataSets)

            // set data
            mChart.data = data
        }
    }

}